package aplicacao.movel.webservice;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import br.usp.fsi.entity.Admin;
import br.usp.fsi.entity.Empresa;
import br.usp.fsi.entity.Local;
import br.usp.fsi.entity.Material;
import br.usp.fsi.entity.Registro;
import br.usp.fsi.entity.Sessao;
import br.usp.fsi.entity.TipoMaterial;
import br.usp.fsi.entity.Usuario;

import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonParser;

public class WebServiceREST {
	
	private static final String URL_SERVER = "http://192.168.1.101:8080/FSI-Server/";
	//private static final String URL_SERVER = "http://10.0.2.2:8080/FSI-Server/";

	 private static final String URL_WS = URL_SERVER + "jersey/webservice/";

	private static final HashMap<Tipo, Class> mapaDeTipos = new HashMap<Tipo, Class>();

	static {
		mapaDeTipos.put(Tipo.Admin, Admin.class);
		mapaDeTipos.put(Tipo.Empresa, Empresa.class);
		mapaDeTipos.put(Tipo.Local, Local.class);
		mapaDeTipos.put(Tipo.Material, Material.class);
		mapaDeTipos.put(Tipo.Registro, Registro.class);
		mapaDeTipos.put(Tipo.TipoMaterial, TipoMaterial.class);
		mapaDeTipos.put(Tipo.Usuario, Usuario.class);
	}

	public Object obterUm(Tipo tipo, int id) throws Exception {

		StringBuilder url = new StringBuilder(URL_WS);
		url.append("obterUm/").append(mapaDeTipos.get(tipo).getSimpleName()).append("/").append(id);

		String[] resposta = new WebServiceBaixoNivel().get(url.toString());

		if (resposta[0].equals("200")) {
			Gson gson = new Gson();
			Object objeto = gson.fromJson(resposta[1], mapaDeTipos.get(tipo));
			return objeto;
		} else {
			throw new Exception(resposta[1]);
		}
	}

	/**
	 * Obt�m todos os elementos cadastrados no banco para a classe T
	 * 
	 * @param T
	 *            classe da qual ser�o obtidos os par�metros
	 * @return {@link List} de todos os elementos presentes no banco
	 * @throws Exception
	 *             caso a resposta signifique que houve erro
	 */
	public <T> List<T> obterTodos(Class T) throws Exception {

		StringBuffer url = new StringBuffer(URL_WS);
		url.append("obterTodos/").append(T.getSimpleName());

		String[] resposta = new WebServiceBaixoNivel().get(url.toString());

		if (resposta[0].equals("200")) {
			JsonArray array = new JsonParser().parse(resposta[1]).getAsJsonArray();

			Gson gson = new Gson();
			ArrayList<T> lista = new ArrayList<T>();

			for (int i = 0; i < array.size(); i++) {
				lista.add((T) gson.fromJson(array.get(i), T));
			}

			return lista;
		} else {
			throw new Exception(resposta[1]);
		}
	}

	/**
	 * Obt�m todos os objetos cadastrados no banco de dados para a classe T que
	 * contenham os atributos que o par�metro objeto cont�m
	 * 
	 * @param objeto
	 *            objeto que servir� de par�metro para buscar no banco todos os
	 *            outros que tenham atributos iguais a ele
	 * @return {@link List} de T que s�o todos os elementos no banco que
	 *         correspondem � restri��o imposta
	 * @throws Exception
	 *             caso a resposta signifique que houve erro
	 */
	public <T> List<T> obterVariosPorParametro(T objeto) throws Exception {

		StringBuffer url = new StringBuffer(URL_WS);
		url.append("obterVariosPorParametro/").append(objeto.getClass().getSimpleName());

		Gson gson = new Gson();
		String objetoJSON = gson.toJson(objeto);

		String[] resposta = new WebServiceBaixoNivel().post(url.toString(), objetoJSON);

		if (resposta[0].equals("200")) {
			JsonArray array = new JsonParser().parse(resposta[1]).getAsJsonArray();

			gson = new Gson();
			ArrayList<T> lista = new ArrayList<T>();

			for (int i = 0; i < array.size(); i++) {
				lista.add((T) gson.fromJson(array.get(i), objeto.getClass()));
			}

			return lista;
		} else {
			throw new Exception(resposta[1]);
		}

	}

	/**
	 * Insere no BD o objeto passado como par�metro.
	 * 
	 * @param objeto
	 *            objeto que ser� inserido no bd
	 * @return o id do objeto que foi inserido no BD.
	 * @throws Exception
	 */
	public int inserirUm(Object objeto) throws Exception {

		StringBuilder url = new StringBuilder(URL_WS);
		url.append("inserir/").append(objeto.getClass().getSimpleName());

		Gson gson = new Gson();
		String objetoJSON = gson.toJson(objeto);

		String[] resposta = new WebServiceBaixoNivel().post(url.toString(), objetoJSON);
		if (resposta[0].equals("200")) {
			return Integer.valueOf(resposta[1]);
		} else {
			throw new Exception(resposta[1]);
		}
	}

	/**
	 * Atualiza as informa��es do objeto passado como par�metro
	 * 
	 * @param objeto
	 *            objeto a ser atualizado no banco de dados
	 * @return <code>true</code> se a atualiza��o der certo, <code>false</code>
	 *         caso contr�rio
	 * @throws Exception
	 */
	public Boolean editarUm(Object objeto) throws Exception {

		StringBuilder url = new StringBuilder(URL_WS);
		url.append("editar/").append(objeto.getClass().getSimpleName());

		Gson gson = new Gson();
		String objetoJSON = gson.toJson(objeto);

		String[] resposta = new WebServiceBaixoNivel().post(url.toString(), objetoJSON);
		if (resposta[0].equals("200")) {
			return Boolean.valueOf(resposta[1]);
		} else {
			throw new Exception(resposta[1]);
		}
	}

	public Boolean deletarUm(Tipo tipo, int id) {
		StringBuilder url = new StringBuilder(URL_WS);
		url.append("deletar/").append(mapaDeTipos.get(tipo)).append("/").append(id);

		String[] resposta = new WebServiceBaixoNivel().get(url.toString());
		return Boolean.valueOf(resposta[1]);
	}

	/**
	 * Dada um usu�rio e uma senha tenta autenticar o usu�rio com a aplica��o
	 * servidor
	 * 
	 * @param usuario
	 * @param senha
	 * @return {@link Sessao} que conter� os dados referentes � sess�o do
	 *         usu�rio logado
	 * @throws Exception
	 */
	public Sessao logar(String usuario, String senha) throws Exception {
		StringBuilder url = new StringBuilder(URL_WS);
		url.append("logar/").append(usuario).append("/").append(criptografar(senha));

		String[] resposta = new WebServiceBaixoNivel().get(url.toString());

		if (resposta[0].equals("200")) {
			Gson gson = new Gson();
			Sessao sessao = gson.fromJson(resposta[1], Sessao.class);
			return sessao;
		} else {
			throw new Exception(resposta[1]);
		}
	}

	private Object criptografar(String senha) {
		// TODO Auto-generated method stub
		return senha;
	}

	public static String getUrlServer() {
		return URL_SERVER;
	}

}
